import wx
from rsa import RSA_ROOT
from wx.lib.mixins.listctrl import ColumnSorterMixin
from rsa.formatter.formatter import FormatterFactory
from rsa.validator import RSA

class AnalyzerOutput(object):
    '''
    This class represent a interface to encapsulate the functionality to
    show violations 
    '''
    
    def show(self, violations):
        raise NotImplementedError("Should have implemented this")

class SimpleAnalyzerOutput(AnalyzerOutput, wx.Frame):
    '''
    A simple implementation of AnalyzerOutput using wxPython
    '''
    
    INITIAL_SIZE = [1100, 400]
    COLUMNS = ["  ", "Description", "Suggestion", "Location", "Line", "Rule"]
    COLSIZE = [30, 300, 300, 200, 40, 200]
    
    # violations table columns
    table = None
    summary = None
    
    def __init__(self, parent, title):
        super(SimpleAnalyzerOutput, self).__init__(parent, title=title,
            size=(self.INITIAL_SIZE[0], self.INITIAL_SIZE[1]))
        self._init_ui()
        
    def _init_ui(self):
        ''' Initialize main UI panel'''
        # create center panel and add all the required controls
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self._init_notebook(panel), 1, wx.ALL | wx.EXPAND, 1)
        panel.SetSizer(sizer)
        self.Layout()
        
    def _init_notebook(self, panel):
        ''' Initialize main notebook and add all the required components '''
        notebook = wx.Notebook(panel, id=wx.ID_ANY, style=wx.BK_DEFAULT)
        # create main panel
        problems = wx.Panel(notebook)
        vbox = wx.BoxSizer(wx.VERTICAL)
        # violations summary label, save this element to be used after
        # the analyzer process the test 
        hb1 = wx.BoxSizer(wx.HORIZONTAL)
        self.summary = wx.StaticText(problems, label='0 items')
        hb1.Add(self.summary, flag=wx.RIGHT, border=8)
        # initialize violations table
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        self.table = ViolationsList(problems, self.COLUMNS, self.COLSIZE)
        hbox.Add(self.table, 1, wx.EXPAND)
        # add components to main panel
        vbox.Add(hb1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border=5)
        vbox.Add((-1, 5))
        vbox.Add(hbox, proportion=1, flag=wx.LEFT | wx.RIGHT | wx.EXPAND, border=10)
        problems.SetSizer(vbox)
        # add main panel to notebook and return component
        notebook.AddPage(problems, "Problems")
        return notebook
    
    def show(self, violations):
        if(violations == None): raise Exception('A violations array is need.')
        if(self.table == None): raise Exception('Violations table was no initialized.')
        self.table._fill_table(violations)
        self.summary.SetLabel(self.get_summary(self.table.severity))
        self.Center()
        self.Show()
        
    def get_summary(self, severity):
        return str(severity[0]) + " errors, " + str(severity[1]) + " warnings, " + str(severity[2]) + " suggestions"

class ViolationsList(wx.ListCtrl, ColumnSorterMixin):
    
    severity = [0, 0, 0]
    images = ["/resources/error.gif","/resources/warn.gif", "/resources/info.gif"]
    itemDataMap = None
       
    def __init__(self, parent, columns, colsize, violations=None):
        wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT)
        # create table header
        for i in range(0, len(columns)):
            self.InsertColumn(i, columns[i])
            self.SetColumnWidth(i, colsize[i])
        #
        self.il = wx.ImageList(16, 16)
        for image in self.images:
            self.il.Add(wx.Bitmap(RSA_ROOT + image))
        self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
        # if violations were given, add them to the table 
        if(violations):
            self._fill_table(violations)
            
    def _fill_table(self, violations):
        # create violations map
        vmap = self.violations_map(violations)
        for key in vmap:
            item = 0
            data = vmap.get(key)
            # track error type
            if(data[0] == 'Error'):
                item = 0
            elif(data[0] == 'Warning'):
                item = 1
            else:
                item = 2
            # fill table
            self.severity[item] += 1
            index = self.InsertImageItem(0, item)
            for i in range(1, len(data)):
                self.SetStringItem(index, i, data[i])      
                self.SetItemData(index, key)     
        self.itemDataMap = vmap
        ColumnSorterMixin.__init__(self, len(data))      
        self.SortListItems(0, True)       
           
    def violations_map(self, violations):
        # get list violations formatter
        formatter = FormatterFactory().get_formatter("list")
        # load violations into a map
        vmap = {}
        for i in range(0, len(violations)):
            data = formatter.format(violations[i])
            vmap[i + 1] = data
        return vmap
    
    def GetListCtrl(self):
        return self